﻿using System;
using System.Collections.Generic;
using System.Text;
using Chaliy.DbPro.Generators.TextAuthoring.Configuration;

namespace Chaliy.DbPro.Generators.TextAuthoring
{
	public class RandomSentanceAuthor : ISentanceAuthor
	{
		#region Fields

		private Random randomSelector;
		private readonly ITermAccessor seprators;
		private readonly ITermAccessor comas;
		private readonly IWordAuthor wordAuthor;
		private int minLength;
		private int maxLength;

		private TermSelector sepratorsTermSelector;
		private TermSelector comasTermSelector;

		#endregion

		#region Constructors

		public RandomSentanceAuthor(ITermAccessor seprators, ITermAccessor comas, IWordAuthor wordAuthor)
		{
			if (seprators == null)
			{
				throw new ArgumentNullException("seprators");
			}
			if (comas == null)
			{
				throw new ArgumentNullException("comas");
			}
			if (wordAuthor == null)
			{
				throw new ArgumentNullException("wordAuthor");
			}
			this.seprators = seprators;
			this.comas = comas;
			this.wordAuthor = wordAuthor;
		}

		#endregion

		#region Properties

		protected Random RandomSelector
		{
			get
			{
				if (this.randomSelector == null)
				{
					this.randomSelector = new Random();
				}
				return this.randomSelector;
			}
		}

		protected ITermAccessor Seprators
		{
			get
			{
				return this.seprators;
			}
		}

		protected ITermAccessor Comas
		{
			get
			{
				return this.comas;
			}
		}

		protected IWordAuthor WordAuthor
		{
			get
			{
				return this.wordAuthor;
			}
		}

		public int MinLength
		{
			get
			{
				return this.minLength;
			}
			set
			{
				this.minLength = value;
			}
		}

		public int MaxLength
		{
			get
			{
				return this.maxLength;
			}
			set
			{
				this.maxLength = value;
			}
		}

		protected TermSelector SepratorsTermSelector
		{
			get
			{
				if (this.sepratorsTermSelector == null)
				{
					this.sepratorsTermSelector = new TermSelector(
						this.Seprators
						);
				}
				return this.sepratorsTermSelector;
			}
		}

		protected TermSelector ComasTermSelector
		{
			get
			{
				if (this.comasTermSelector == null)
				{
					this.comasTermSelector = new TermSelector(
						this.Comas
						);
				}
				return this.comasTermSelector;
			}
		}

		#endregion

		#region ISentanceAuthor Members

		public string Generate()
		{
			int minLenght = this.MinLength;
			int maxLenght = this.MaxLength;

			int lengh = this.RandomSelector.Next(minLenght, maxLenght);

			StringBuilder sentanceBuffer = new StringBuilder();

			for (int i = 0; i < lengh; i++)
			{
				sentanceBuffer.Append(this.GenerateWord());
				if (this.CanInsertComa(i, lengh))
				{
					sentanceBuffer.Append(this.GenerateComa());
				}
				if (i < lengh - 1)
				{
					sentanceBuffer.Append(" ");
				}
			}

			// Make first char UPPERCASE
			if (sentanceBuffer.Length > 0)
			{
				sentanceBuffer[0] = Char.ToUpperInvariant(sentanceBuffer[0]);
			}

			// Append period, question mark or something like this
			sentanceBuffer.Append(this.GenerateSeparator());

			return sentanceBuffer.ToString();
		}		

		#endregion

		#region Methods

		private bool CanInsertComa(int wordIndex, int length)
		{
			if (wordIndex != length - 1)
			{
				return this.RandomSelector.Next(length) == wordIndex;
			}
			return false;
		}

		protected virtual string GenerateSeparator()
		{
			return this.SepratorsTermSelector.GetNextTerm();
		}

		protected virtual string GenerateComa()
		{
			return this.ComasTermSelector.GetNextTerm();
		}

		private string GenerateWord()
		{
			return this.WordAuthor.Generate();
		}

		#endregion
	}
}
